package code

import (
	"go/ast"
	"strings"
)

// InterfaceSpec is a definition of the interface
type InterfaceSpec struct {
	Name    string
	Methods []*Function
}

// InterfaceSpecs is a group of InterfaceSpec model
type InterfaceSpecs []*InterfaceSpec

// ByName return interface by name Another return value shows whether there is an interface
// with that name exists.
func (intfs InterfaceSpecs) ByName(name string) (*InterfaceSpec, bool) {
	for _, intf := range intfs {
		if intf.Name == name {
			return intf, true
		}
	}
	return nil, false
}

// Param is a model of method parameter
type Param struct {
	Name string
	Type Type
}

func ExtractInterfaceSpec(spec *ast.TypeSpec, iType *ast.InterfaceType) *InterfaceSpec {

	name := spec.Name.Name
	intf := InterfaceSpec{
		Name: name,
	}

	for _, method := range iType.Methods.List {
		funcType, ok := method.Type.(*ast.FuncType)
		if !ok {
			continue
		}

		var methodName string
		for _, n := range method.Names {
			methodName = n.Name
			break
		}

		var comments []string
		if method.Doc != nil {
			for _, comment := range method.Doc.List {
				commentRunes := []rune(comment.Text)
				commentText := strings.TrimSpace(string(commentRunes[2:]))
				comments = append(comments, commentText)
			}
		}

		meth := ExtractFunction(methodName, comments, funcType)

		intf.Methods = append(intf.Methods, meth)
	}

	return &intf
}
